package zara
import grails.converters.*
import java.util.Calendar
import org.springframework.security.providers.UsernamePasswordAuthenticationToken as AuthToken
import org.springframework.security.context.SecurityContextHolder as SCH


class ApiController {
    def authenticateService
    def daoAuthenticationProvider
    def helperService
    def executorsService

    def index = { // 0 skip ,1 ok , 10 ,manager
        log.info( "api index params.id = ${params.id}") 
        Machine mac = Machine.findByMac(params.id ,  [cache:false])
        if (!mac) {
            return render("0")
        }
 
        if (!params.ip) {
            String ip = request.getHeader("x-forwarded-for");       
            if(!ip   || "unknown".equalsIgnoreCase(ip)) {       
                ip = request.getHeader("Proxy-Client-IP");       
            }       
            if(!ip || "unknown".equalsIgnoreCase(ip)) {       
                ip = request.getHeader("WL-Proxy-Client-IP");       
            }       
            if(!ip || "unknown".equalsIgnoreCase(ip)) {       
                ip = request.getRemoteAddr();       
            }       
            params.ip = ip; 
        }
        log.info( "api index params.ip = ${params.ip}") 

        if (mac.manage) {
            new Ip(source : params.id , address: params.ip , success : false).save() 
            return render("2")
        }

        def count = Ip.lastIp(params.ip.toString())
        log.info( "api index Ip.lastIp = ${count}")  

        new Ip(source : params.id , address: params.ip , success : count == 0).save() 
        render(count == 0 ? '1' : '0')
     
        
    }
 

    def website = { 
        def getTaskNumber = 10;
        def userc = servletContext["${params.u}"]
        User aUser = User.get(userc)
        def getLoopTimes = params.n?params.int('n'):0

        def  result = []
        def websites = []
        /////////////////////////////////////////////////////////
        //把这个底下的循环改一下,应该先取出所有能够用的数据，再开始进行数据的转换JSON处理
        //1 还需要再判断是不是今天已经被这个ip刷过了，如果刷过了，就不刷了,如果这个站今天刷的次数已经够了,也不刷了
        //2 还有一种,用户能刷多少次就刷多少次,只要不超过站点指定的能被刷的次数.当然这种情况的前提是网站非常多的时候.否则一会儿就被刷干净了.
        //先按照1的情况来完成
        ////////////////////////////////////////////////////////
        def websiteList = servletContext['websiteList']
        def webs = []
        def logs = Ip.withCriteria{
            eq("person",User.get(userc))
            between("lastTime",new Date().minus(1),new Date())
        }
        websiteList.each{
            def has = logs.every{ elem ->
                it != elem.website.id
            }
            if(has){
                webs.add(it)
            }
        }
        // def ws = Website.list() 
        def ws = Website.withCriteria {
            ne('person', aUser)
            sizeGt('tasks',0)
            tasks{
                eq('available',true)
            }
            person{
                or{
                    eq('vip',true)
                    ge('total',1)
                }
            }
            'in'('id',webs)
            firstResult(getTaskNumber*getLoopTimes)
            maxResults(10)            
        }
        //def ws = Website.findAllByPerson(User.get(userc),[offset:(getTaskNumber*getLoopTimes)]) 

        log.info("Website total : ${ws.size()}")
        
        Calendar   calendar   =   Calendar.getInstance();
        def int now_hour = calendar.get(Calendar.HOUR_OF_DAY)

       
        def pass 
        // 循环站点，并找出可以执行的任务
        // 站点可以用两种方式限制访问的次数和频率
        // 一种是设置HourRate，设置每个小时可以点击的次数。
        // 第二种是在一个website下设置多个Task，这样每个Task根据自己的权重，都有机会被执行。
        // 也可以两种一起设置。
        // 我认为互联网模式的情况下，是不应该有加权值的概念的，只是需要限制此站点应该每天被点击多少次就可以。
        
        ws.each{ website ->
            /////////// 通过HourRate判断这个Website可不可以执行
            pass = true
            if (website.dayOfhit != now_hour) {// 新的小时，清零计数器
                website.total = 0
            }
            
            log.info(website.dayOfhit +"||"+ now_hour);

            pass = website.rateMatch()

            ///////  返回task
            //log.info(website.name + " pass = " + pass);
            if (pass) {
                websites.add(website)
                // 通过时间验证的才可以执行
                //def tasks = Task.findAllByWebsiteAndAvailable(website,true);
                def tasks = Task.findAllByWebsiteAndAvailable(website,true);
                if (tasks && !tasks.isEmpty()) {
                    def seek = Math.random() * tasks?.seek.sum()
                    def tasks_count=0;
                    def f = true;
                    tasks.each{ v  ->
                        tasks_count += v.seek;
                        if (tasks_count > seek && f) { //可用的任务 
                            def content = v.buildToJSON()
                            if (content != '') {
                                result.add( "\"${content}\"")
                                f = false;
                                website.total = website.total + 1
                            }
                       }
                    } 
                }
            }
            website.dayOfhit = now_hour
            //log.info(website.name + "save to :" + website.save(flush:true))
            if (!website.save(flush:true)) {
                website.errors.each {
                    println it
                }
            }
        }
        // 刷新记录的保存  START

        executorsService.save(websites,userc,request)
        // 刷新记录的保存  END
        //return render(result as JSON) 
        if (result.size() == 0) {
            render(contentType:"text/json",text : "[\"sleep,${3}\"]")  
        }else{
            // 此位置是预留给记录日志用
            //Ip ip = new Ip();
            //ip.
            render(contentType:"text/json",text : "[${result.join(',')}]")  
        }
    }
    static String version = "Givenchy 0.2";
    static String updateURL = "";

    def update = {
       render( "${ApiController.version}|${ApiController.updateURL}")
    }

    def login = {    
            def loginInfo = ""
            if(params.u == "admin"){
                loginInfo = "登录失败，请检查用户名和密码！"
            }else{
                def userCurrent = User.findByUsernameAndEnabled(params.u,true)
                if(userCurrent){ 
                    def codeStr = helperService.hashBase64("user"+userCurrent.id)
                    codeStr = helperService.reEncode(codeStr)
                    servletContext[codeStr] = userCurrent.id
                    loginInfo = "success|${codeStr}"
                }else{
                    loginInfo = "登录失败，请检查用户名和密码！"
                }
            }
            return render("${loginInfo}")
    }

    def isLogin = {
    def userContext = params.u
        def isLogin = servletContext[userContext]?"1":"0"   
        return render("${isLogin}")
    }

    def logout = {
        def userContext = params.u
        if(servletContext[userContext]){
            servletContext.removeAttribute(userContext)
        }
    }
}
